home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / 2.11news / patch04 < prev    next >
Encoding:
Text File  |  1987-02-23  |  31.7 KB  |  1,350 lines

  1. /* Written 11:08 pm  Feb 23, 1987 by rick@seismo.UUCP in mirror:news.software.b */
  2. /* ---------- "Patch #4 for 2.11 news src" ---------- */
  3. Description:
  4.     This is patch #4 for news 2.11 source. It addresses the following
  5.     problems:
  6.  
  7.     A minor optimization for checknews.
  8.     Handle trailing white space better in control messages.
  9.     If you are running with history subdirectories (i.e. you don't have
  10.     dbm), you don't need the history file anymore.
  11.     Fix the STUPID typo in patch#3 that could have unlinked the active file.
  12.     Fix some portability problems with the readnews/vnews 'l' command.
  13.     A few minor cleanups.
  14.  
  15. Fix:
  16.     cd to the src directory and apply the following patch
  17.  
  18. Index: checknews.c
  19. Prereq: 2.27
  20. *** .d/checknews.c    Wed Dec 17 18:23:00 1986
  21. --- checknews.c    Mon Feb 23 22:28:20 1987
  22. ***************
  23. *** 16,22 ****
  24.    */
  25.   
  26.   #ifdef SCCSID
  27. ! static char    *SccsId = "@(#)checknews.c    2.27    12/16/86";
  28.   #endif /* SCCSID */
  29.   
  30.   char *Progname = "checknews";        /* used by xerror */
  31. --- 16,22 ----
  32.    */
  33.   
  34.   #ifdef SCCSID
  35. ! static char    *SccsId = "@(#)checknews.c    2.28    2/22/87";
  36.   #endif /* SCCSID */
  37.   
  38.   char *Progname = "checknews";        /* used by xerror */
  39. ***************
  40. *** 238,243 ****
  41. --- 238,245 ----
  42.   #ifdef DEBUG
  43.           fprintf(stderr, "bfr = '%s'\n", bfr);
  44.   #endif
  45. +         if (narts == 0)
  46. +             continue;
  47.           ngcat(bfr);
  48.           if (!ngmatch(bfr, nflag ? narggrp : header.nbuf))
  49.               continue;
  50.  
  51. Index: control.c
  52. Prereq: 2.50
  53. *** .d/control.c    Mon Dec 29 18:34:10 1986
  54. --- control.c    Mon Feb 23 22:28:30 1987
  55. ***************
  56. *** 19,25 ****
  57.    */
  58.   
  59.   #ifdef SCCSID
  60. ! static char    *SccsId = "@(#)control.c    2.50    12/29/86";
  61.   #endif /* SCCSID */
  62.   
  63.   #include "iparams.h"
  64. --- 19,25 ----
  65.    */
  66.   
  67.   #ifdef SCCSID
  68. ! static char    *SccsId = "@(#)control.c    2.51    2/22/87";
  69.   #endif /* SCCSID */
  70.   
  71.   #include "iparams.h"
  72. ***************
  73. *** 127,140 ****
  74.   
  75.       while (*str) {
  76.           if (*str <= ' ') {
  77. -             *nextfree++ = 0;
  78. -             cargv[cargc] = nextfree;
  79. -             cargc++;
  80.               /* skip over white space */
  81.               while (*str != '\0' && *str <= ' ')
  82.                   str++;
  83.               if (*str == '\0')    /* line ends in white space */
  84.                   return;
  85.           } else
  86.               *nextfree++ = *str++;
  87.       }
  88. --- 127,140 ----
  89.   
  90.       while (*str) {
  91.           if (*str <= ' ') {
  92.               /* skip over white space */
  93.               while (*str != '\0' && *str <= ' ')
  94.                   str++;
  95.               if (*str == '\0')    /* line ends in white space */
  96.                   return;
  97. +             *nextfree++ = 0;
  98. +             cargv[cargc] = nextfree;
  99. +             cargc++;
  100.           } else
  101.               *nextfree++ = *str++;
  102.       }
  103.  
  104. Index: expire.c
  105. Prereq: 2.49
  106. *** .d/expire.c    Wed Dec 17 18:23:08 1986
  107. --- expire.c    Mon Feb 23 22:28:40 1987
  108. ***************
  109. *** 17,23 ****
  110.    */
  111.   
  112.   #ifdef SCCSID
  113. ! static char    *SccsId = "@(#)expire.c    2.49    12/16/86";
  114.   #endif /* SCCSID */
  115.   
  116.   #include "params.h"
  117. --- 17,23 ----
  118.    */
  119.   
  120.   #ifdef SCCSID
  121. ! static char    *SccsId = "@(#)expire.c    2.50    2/22/87";
  122.   #endif /* SCCSID */
  123.   
  124.   #include "params.h"
  125. ***************
  126. *** 54,67 ****
  127.   char    recdate[BUFLEN];
  128.   long    rectime, exptime;
  129.   extern char *OLDNEWS;
  130. ! int    verbose = 0;
  131. ! int    ignorexp = 0;
  132. ! int    doarchive = 0;
  133. ! int    nohistory = 0;
  134. ! int    dorebuild = 0;
  135. ! int    usepost = 0;
  136. ! int    frflag = 0;
  137. ! int    updateactive = 0;
  138.   char    baduser[BUFLEN];
  139.   extern     char filename[], nbuf[];
  140.   
  141. --- 54,68 ----
  142.   char    recdate[BUFLEN];
  143.   long    rectime, exptime;
  144.   extern char *OLDNEWS;
  145. ! int    verbose = 0;        /* output trace information */
  146. ! int    ignorexp = 0;        /* ignore Expire: lines */
  147. ! int    doarchive = 0;        /* archive articles in SPOOL/oldnews */
  148. ! int    nohistory = 0;        /* ignore history file */
  149. ! int    dorebuild = 0;        /* rebuild history file */
  150. ! int    dorbldhistory = 0;    /* rebuild history.d directory */
  151. ! int    usepost = 0;        /* use posting date to expire */
  152. ! int    frflag = 0;        /* expire specific user */
  153. ! int    doupdateactive = 0;    /* update ACTIVE file */
  154.   char    baduser[BUFLEN];
  155.   extern     char filename[], nbuf[];
  156.   
  157. ***************
  158. *** 79,88 ****
  159. --- 80,93 ----
  160.   char *realloc();
  161.   struct tm *gmtime();
  162.   
  163. + #ifdef DBM
  164.   typedef struct {
  165.       char *dptr;
  166.       int dsize;
  167.   } datum;
  168. + #else
  169. + FILE *nexthistfile();
  170. + #endif /* !DBM */
  171.   
  172.   long    expincr;
  173.   long    dropincr;
  174. ***************
  175. *** 99,123 ****
  176.   char    grpsleft[BUFLEN];
  177.   struct hbuf h;
  178.   int    ExpireLock;
  179.   
  180.   main(argc, argv)
  181.   int    argc;
  182.   char    **argv;
  183.   {
  184. -     register char    *p1, *p2, *p3;
  185. -     register time_t newtime, today;
  186. -     register FILE *fp = NULL;
  187. -     FILE    *ohfd, *nhfd;
  188. -     DIR    *ngdirp = NULL;
  189. -     static struct direct *ngdir;
  190. -     char fn[BUFLEN];
  191. -     int i, LockFd;
  192. - #ifndef DBM
  193. -     char *ptr, chr;
  194. -     FILE *subfd[10];
  195. -     char *histfile();
  196. - #endif /* !DBM */
  197.       pathinit();
  198.       (void) umask(N_UMASK);
  199.   
  200. --- 104,116 ----
  201.   char    grpsleft[BUFLEN];
  202.   struct hbuf h;
  203.   int    ExpireLock;
  204. + int    rmlock();
  205. + time_t    today;
  206.   
  207.   main(argc, argv)
  208.   int    argc;
  209.   char    **argv;
  210.   {
  211.       pathinit();
  212.       (void) umask(N_UMASK);
  213.   
  214. ***************
  215. *** 134,139 ****
  216. --- 127,136 ----
  217.       (void) setgid(gid);
  218.       (void) setuid(uid);
  219.   
  220. +     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  221. +         signal(SIGHUP, rmlock);
  222. +     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  223. +         signal(SIGINT, rmlock);
  224.       expincr = DFLTEXP;
  225.       dropincr = HISTEXP;
  226.       ngpat[0] = ',';
  227. ***************
  228. *** 233,242 ****
  229.               dorebuild++;
  230.               nohistory++;
  231.               break;
  232. !         case 'p':
  233.               usepost++;
  234.               break;
  235. !         case 'f':
  236.               frflag++;
  237.               if (argc > 2) {
  238.                   strcpy(baduser, argv[2]);
  239. --- 230,239 ----
  240.               dorebuild++;
  241.               nohistory++;
  242.               break;
  243. !         case 'p':    /* use posting date to expire */
  244.               usepost++;
  245.               break;
  246. !         case 'f':    /* expire messages from baduser */
  247.               frflag++;
  248.               if (argc > 2) {
  249.                   strcpy(baduser, argv[2]);
  250. ***************
  251. *** 244,259 ****
  252.                   argc--;
  253.               }
  254.               break;
  255. !         case 'u':
  256. !             updateactive++;
  257.               break;
  258.           default:
  259. !             printf("Usage: expire [ -v [level] ] [-e days ] [-i] [-a] [-r] [-h] [-p] [-u] [-f username] [-n newsgroups]\n");
  260.               xxit(1);
  261.           }
  262.           argc--;
  263.           argv++;
  264.       }
  265.       if (dropincr < expincr) {
  266.           dropincr = HISTEXP;
  267.           fprintf(stderr, "History expiration time < article expiration time. Default used.\n");
  268. --- 241,265 ----
  269.                   argc--;
  270.               }
  271.               break;
  272. !         case 'u':    /* update the active file from 2.10.1 fmt */
  273. !             doupdateactive++;
  274.               break;
  275. +         case 'H':    /* convert to history.d format */
  276. +             dorbldhistory++;
  277. +             break;
  278.           default:
  279. !             printf("Usage: expire [ -v [level] ] [-e days ] [-i] [-a] [-r] [-h] [-p] [-u] [-f username] [-n newsgroups] [-H]\n");
  280.               xxit(1);
  281.           }
  282.           argc--;
  283.           argv++;
  284.       }
  285. +     if (dorbldhistory) {
  286. + #ifndef DBM
  287. +         rebuildhistorydir();
  288. + #endif /* !DBM */
  289. +         exit(0);
  290. +     }
  291.       if (dropincr < expincr) {
  292.           dropincr = HISTEXP;
  293.           fprintf(stderr, "History expiration time < article expiration time. Default used.\n");
  294. ***************
  295. *** 275,289 ****
  296.               printf("archiving: %s\n",arpat);
  297.       }
  298.   
  299.       (void) sprintf(OARTFILE, "%s/%s", LIB, "ohistory");
  300.       (void) sprintf(NARTFILE, "%s/%s", LIB, "nhistory");
  301.   
  302.       (void) sprintf(OACTIVE, "%s/%s", LIB, "oactive");
  303.       (void) sprintf(NACTIVE, "%s/%s", LIB, "nactive");
  304.   
  305. !     if (updateactive)
  306. !         goto doupdateactive;
  307.   
  308.   #ifdef DBM
  309.       if (!dorebuild) {
  310.           (void) sprintf(PAGFILE, "%s/%s", LIB, "nhistory.pag");
  311. --- 281,327 ----
  312.               printf("archiving: %s\n",arpat);
  313.       }
  314.   
  315. + #ifdef DBM
  316.       (void) sprintf(OARTFILE, "%s/%s", LIB, "ohistory");
  317. + #endif /* DBM */
  318.       (void) sprintf(NARTFILE, "%s/%s", LIB, "nhistory");
  319.   
  320.       (void) sprintf(OACTIVE, "%s/%s", LIB, "oactive");
  321.       (void) sprintf(NACTIVE, "%s/%s", LIB, "nactive");
  322.   
  323. !     if (!doupdateactive) {
  324. !         expire();
  325. ! #ifndef DBM
  326. !         rebuildhistorydir();
  327. ! #endif
  328. !     }
  329.   
  330. +     updateactive();
  331. +     rmlock();
  332. +     /*
  333. +      * Now read in any saved news.
  334. +      */
  335. + #ifdef PROFILING
  336. +     monitor((int(*)())0,(int(*)())0,0,0,0);
  337. + #endif /* PROFILING */
  338. +     execl(RNEWS, "rnews", "-U", (char *)NULL);
  339. +     perror(RNEWS);
  340. +     xxit(1);
  341. +     /* NOTREACHED */
  342. + }
  343. + expire()
  344. + {
  345. +     register char    *p1, *p2, *p3;
  346. +     register time_t newtime;
  347. +     register FILE *fp = NULL;
  348. +     FILE    *ohfd, *nhfd;
  349. +     int i;
  350. +     char    fn[BUFLEN];
  351. +     DIR    *ngdirp = NULL;
  352. +     static struct direct *ngdir;
  353.   #ifdef DBM
  354.       if (!dorebuild) {
  355.           (void) sprintf(PAGFILE, "%s/%s", LIB, "nhistory.pag");
  356. ***************
  357. *** 290,296 ****
  358.           (void) sprintf(DIRFILE, "%s/%s", LIB, "nhistory.dir");
  359.           (void) close(creat(PAGFILE, 0666));
  360.           (void) close(creat(DIRFILE, 0666));
  361. !          initdbm(NARTFILE);
  362.       }
  363.   #endif
  364.   
  365. --- 328,334 ----
  366.           (void) sprintf(DIRFILE, "%s/%s", LIB, "nhistory.dir");
  367.           (void) close(creat(PAGFILE, 0666));
  368.           (void) close(creat(DIRFILE, 0666));
  369. !         initdbm(NARTFILE);
  370.       }
  371.   #endif
  372.   
  373. ***************
  374. *** 297,304 ****
  375.       if (nohistory) {
  376.           ohfd = xfopen(ACTIVE, "r");
  377.           if (dorebuild) {
  378. !             /* Allocate initial space for multiple newsgroup (for an
  379. !                article) array */
  380.               multhist = (struct multhist *)calloc (SPACE_INCREMENT,
  381.                       sizeof (struct multhist));
  382.               mh_size = SPACE_INCREMENT;
  383. --- 335,342 ----
  384.       if (nohistory) {
  385.           ohfd = xfopen(ACTIVE, "r");
  386.           if (dorebuild) {
  387. !             /* Allocate initial space for multiple newsgroup (for
  388. !                an article) array */
  389.               multhist = (struct multhist *)calloc (SPACE_INCREMENT,
  390.                       sizeof (struct multhist));
  391.               mh_size = SPACE_INCREMENT;
  392. ***************
  393. *** 309,336 ****
  394.           } else
  395.               nhfd = xfopen("/dev/null", "w");
  396.       } else {
  397.           ohfd = xfopen(ARTFILE, "r");
  398.           nhfd = xfopen(NARTFILE, "w");
  399.       }
  400.   
  401. !     /* set up exclusive locking so inews doesn't run while expire does */
  402. ! #if defined(BSD4_2) || defined(LOCKF)
  403. !     LockFd = open(ACTIVE, 2);
  404. ! #ifdef    LOCKF
  405. !     (void) lockf(LockFd, F_LOCK, 0);
  406. ! #else    /* BSD4_2 */
  407. !     (void) flock(LockFd, LOCK_EX);
  408. ! #endif    /* BSd4_2 */
  409. ! #else    /* !BSD4_2 && !LOCKF */
  410. !     i = 0;
  411. !     sprintf(afline,"%s.lock", ACTIVE);
  412. !     while (LINK(ACTIVE, afline) < 0 && errno == EEXIST) {
  413. !         if (i++ > 5)
  414. !             xerror("Can't get lock for expire");
  415. !         sleep(i*2);
  416. !     }
  417. !         
  418. ! #endif    /* !BSD4_2  && !LOCKF */
  419.   
  420.       for(i=0;i<NUNREC;i++)
  421.           h.unrec[i] = NULL;
  422. --- 347,361 ----
  423.           } else
  424.               nhfd = xfopen("/dev/null", "w");
  425.       } else {
  426. + #ifdef DBM
  427.           ohfd = xfopen(ARTFILE, "r");
  428. + #else
  429. +         ohfd = nexthistfile((FILE *)NULL);
  430. + #endif /* DBM */
  431.           nhfd = xfopen(NARTFILE, "w");
  432.       }
  433.   
  434. !     dolock();
  435.   
  436.       for(i=0;i<NUNREC;i++)
  437.           h.unrec[i] = NULL;
  438. ***************
  439. *** 375,382 ****
  440. --- 400,415 ----
  441.               fp = access(filename, 04) ? NULL : art_open(filename, "r");
  442.           } else {
  443.               char dc;
  444. + #ifdef DBM
  445.               if (fgets(afline, BUFLEN, ohfd) == NULL)
  446.                   break;
  447. + #else
  448. +             if (fgets(afline, BUFLEN, ohfd) == NULL)
  449. +                 if (!(ohfd = nexthistfile(ohfd)))
  450. +                     break;
  451. +                 else
  452. +                     continue;
  453. + #endif /* DBM */
  454.               if (verbose > 2)
  455.                   printf("article: %s", afline);
  456.               p1 = index(afline, '\t');
  457. ***************
  458. *** 429,438 ****
  459.               } else {
  460.                   /*
  461.                    * Nothing after the 2nd tab.  This happens
  462. !                  * when there's no message left in the spool
  463.                    * directory, only the memory of it in the
  464. !                  * history file. Use date in the history file
  465. !                  * to decide if we should keep this article.
  466.                    */
  467.                   grpsleft[0] = '\0';
  468.                   goto checkdate;
  469. --- 462,472 ----
  470.               } else {
  471.                   /*
  472.                    * Nothing after the 2nd tab.  This happens
  473. !                  * when there is no message left in the spool
  474.                    * directory, only the memory of it in the
  475. !                  * history file. (That is, it got cancelled
  476. !                  * or expired.) Use date in the history file
  477. !                  * to decide if we should keep the memory.
  478.                    */
  479.                   grpsleft[0] = '\0';
  480.                   goto checkdate;
  481. ***************
  482. *** 439,445 ****
  483.               }
  484.               if (!ngmatch(nbuf, ngpat) ||
  485.                    ((rectime+expincr > today) && !dorebuild &&
  486. !                      !frflag && !usepost && recdate[0] != ' '))
  487.                   goto keephist;
  488.               if (!dorebuild && !frflag && !usepost &&
  489.                   recdate[0] != ' ') {
  490. --- 473,479 ----
  491.               }
  492.               if (!ngmatch(nbuf, ngpat) ||
  493.                    ((rectime+expincr > today) && !dorebuild &&
  494. !                  !frflag && !usepost && recdate[0] != ' '))
  495.                   goto keephist;
  496.               if (!dorebuild && !frflag && !usepost &&
  497.                   recdate[0] != ' ') {
  498. ***************
  499. *** 526,533 ****
  500.                * and this code changes it to a.b.c/4 (the correct
  501.                * kind of entry in the history file.)
  502.                *
  503. !              * This can't be a strcpy because the addresses overlap
  504. !              * and some machines can't handle that.
  505.                */
  506.               p1 = filename;
  507.               cp = p1 + strlen(SPOOL);
  508. --- 560,567 ----
  509.                * and this code changes it to a.b.c/4 (the correct
  510.                * kind of entry in the history file.)
  511.                *
  512. !              * This cannot be a strcpy because the addresses
  513. !              * overlap and some machines cannot handle that.
  514.                */
  515.               p1 = filename;
  516.               cp = p1 + strlen(SPOOL);
  517. ***************
  518. *** 578,584 ****
  519.   
  520.               /*
  521.                * Here is where we realloc the multhist space rather
  522. !              * than the old way of static allocation.  It's
  523.                * really trivial.  We just clear out the space
  524.                * in case it was reused.  The old static array was
  525.                * guaranteed to be cleared since it was cleared when
  526. --- 612,618 ----
  527.   
  528.               /*
  529.                * Here is where we realloc the multhist space rather
  530. !              * than the old way of static allocation.  It is
  531.                * really trivial.  We just clear out the space
  532.                * in case it was reused.  The old static array was
  533.                * guaranteed to be cleared since it was cleared when
  534. ***************
  535. *** 648,656 ****
  536. --- 682,694 ----
  537.                   printf("Drop history of %s - %s\n",
  538.                       h.ident, recdate);
  539.           } else {
  540. + #ifdef DBM
  541.               long hpos;
  542. + #endif /* DBM */
  543.   keephist:
  544. + #ifdef DBM
  545.               hpos = ftell(nhfd);
  546. + #endif /* DBM */
  547.   
  548.               if (verbose > 3)
  549.                   printf("Retain history of %s - %s\n",
  550. ***************
  551. *** 693,703 ****
  552.                           rectime = statb.st_mtime;
  553.                   }
  554.                   tm = gmtime(&rectime);
  555. !                 if (
  556.   #ifdef USG
  557. !                     fprintf(nhfd,"%s\t%s%2.2d/%2.2d/%d %2.2d:%2.2d\t%s\n",
  558.   #else /* !USG */
  559. !                     fprintf(nhfd,"%s\t%s%02d/%02d/%d %02d:%02d\t%s\n",
  560.   #endif /* !USG */
  561.                       h.ident, h.expdate[0] ? " " : "",
  562.                       tm->tm_mon+1, tm->tm_mday, tm->tm_year,
  563. --- 731,741 ----
  564.                           rectime = statb.st_mtime;
  565.                   }
  566.                   tm = gmtime(&rectime);
  567. !                 if ( fprintf(nhfd,
  568.   #ifdef USG
  569. !                     "%s\t%s%2.2d/%2.2d/%d %2.2d:%2.2d\t%s\n",
  570.   #else /* !USG */
  571. !                     "%s\t%s%02d/%02d/%d %02d:%02d\t%s\n",
  572.   #endif /* !USG */
  573.                       h.ident, h.expdate[0] ? " " : "",
  574.                       tm->tm_mon+1, tm->tm_mday, tm->tm_year,
  575. ***************
  576. *** 714,720 ****
  577. --- 752,760 ----
  578.               xerror("History write failed, %s", errmsg(errno));
  579.   
  580.       if (dorebuild || !nohistory) {
  581. + #ifndef DBM
  582.           (void) rename(ARTFILE, OARTFILE);
  583. + #endif /* !DBM */
  584.           (void) rename(NARTFILE, ARTFILE);
  585.   #ifdef DBM
  586.           if (dorebuild)
  587. ***************
  588. *** 730,759 ****
  589.           }
  590.   #endif
  591.       }
  592. ! #ifndef DBM
  593. !     /* rebuild history subfiles */
  594. !     for (i = 0; i < 10; i++) {
  595. !         (void) sprintf(fn, "%s.d/%c", ARTFILE, i + '0');
  596. !         close(creat(fn, 0644));
  597. !         subfd[i] = xfopen(fn, "w+");
  598.       }
  599. -     ohfd = xfopen(ARTFILE, "r");
  600. -     while (fgets(fn, BUFLEN, ohfd) != NULL) {
  601. -         ptr = histfile(fn);
  602. -         chr = *(ptr + strlen(ptr) - 1);
  603. -         if (isdigit(chr))
  604. -             i = chr - '0';
  605. -         else
  606. -             i = 0;
  607. -         fputs(fn, subfd[i]);
  608. -     }
  609. -     (void) fclose(ohfd);
  610. -     for (i = 0; i < 10; i++)
  611. -         if (ferror(subfd[i]) || fclose(subfd[i]))
  612. -             xerror("History subfile write");
  613. - #endif /* !DBM */
  614.   
  615. ! doupdateactive:
  616.       ohfd = xfopen(ACTIVE, "r");
  617.       nhfd = xfopen(NACTIVE, "w");
  618.       do {
  619. --- 770,822 ----
  620.           }
  621.   #endif
  622.       }
  623. ! }
  624. ! #if defined(BSD4_2) || defined(LOCKF)
  625. ! static int LockFd = -1;
  626. ! #endif
  627. ! dolock()
  628. ! {
  629. !     /* set up exclusive locking so inews does not run while expire does */
  630. ! #if defined(BSD4_2) || defined(LOCKF)
  631. !     LockFd = open(ACTIVE, 2);
  632. ! # ifdef    LOCKF
  633. !     (void) lockf(LockFd, F_LOCK, 0);
  634. ! # else    /* BSD4_2 */
  635. !     (void) flock(LockFd, LOCK_EX);
  636. ! # endif    /* BSd4_2 */
  637. ! #else    /* !BSD4_2 && !LOCKF */
  638. !     int i = 0;
  639. !     sprintf(afline,"%s.lock", ACTIVE);
  640. !     while (LINK(ACTIVE, afline) < 0 && errno == EEXIST) {
  641. !         if (i++ > 5)
  642. !             xerror("Can't get lock for expire");
  643. !         sleep(i*2);
  644.       }
  645.   
  646. ! #endif    /* !BSD4_2  && !LOCKF */
  647. ! }
  648. ! rmlock()
  649. ! {
  650. ! #if defined(BSD4_2) || defined(LOCKF)
  651. !     close(LockFd);
  652. ! #else
  653. !     sprintf(bfr, "%s.lock", ACTIVE);
  654. !     (void) UNLINK(bfr);
  655. ! #endif    /* !BSD4_2 */
  656. ! }
  657. ! updateactive()
  658. ! {
  659. !     register char    *p1;
  660. !     FILE    *ohfd, *nhfd;
  661. !     DIR    *ngdirp = NULL;
  662. !     static struct direct *ngdir;
  663. !     if (verbose)
  664. !         printf("updating active file %s\n", ACTIVE);
  665.       ohfd = xfopen(ACTIVE, "r");
  666.       nhfd = xfopen(NACTIVE, "w");
  667.       do {
  668. ***************
  669. *** 768,773 ****
  670. --- 831,838 ----
  671.           if (sscanf(afline,"%s %ld %ld %c",nbuf,&maxart, &minart,
  672.               &cansub) < 4)
  673.               xerror("Active file corrupt");
  674. +         if (verbose > 3)
  675. +             printf("looking at group %s\n", nbuf);
  676.           if (!ngmatch(nbuf, ngpat)) {
  677.               if (fputs(afline, nhfd) == EOF)
  678.                   xerror("active file write failed");
  679. ***************
  680. *** 800,823 ****
  681.           afline[gdsize] = '\0';
  682.           if (minart > maxart)
  683.               minart = maxart;
  684.           if (fprintf(nhfd,"%s %05ld %05ld %c\n", afline, maxart,
  685.               minart, cansub) == EOF)
  686.               xerror("Active file write failed");
  687.       } while (!feof(ohfd));
  688.       if (fclose(nhfd))
  689.           xerror("Active file write failed, %s", errmsg(errno));
  690. !     (void) fclose(ohfd); /* unlocking inews as a side effect */
  691. ! #ifndef BSD4_2
  692. !     sprintf(bfr, "%s.lock", ACTIVE);
  693. !     (void) UNLINK(bfr);
  694. ! #endif    /* !BSD4_2 */
  695.   
  696.       (void) rename(ACTIVE, OACTIVE);
  697.       (void) rename(NACTIVE, ACTIVE);
  698. -     execl(RNEWS, "rnews", "-U", (char *)NULL);
  699. -     perror(RNEWS);
  700. -     xxit(1);
  701.   }
  702.   
  703.   /* Unlink (using unwound tail recursion) all the articles in 'artlist'. */
  704. --- 865,892 ----
  705.           afline[gdsize] = '\0';
  706.           if (minart > maxart)
  707.               minart = maxart;
  708. + #ifdef USG
  709. +         if (verbose > 4)
  710. +             printf("\tmaxart = %5.5ld, minart = %5.5ld\n",
  711. +                 maxart, minart);
  712. +         if (fprintf(nhfd,"%s %5.5ld %5.5ld %c\n", afline, maxart,
  713. +             minart, cansub) == EOF)
  714. +             xerror("Active file write failed");
  715. + #else
  716. +         if (verbose > 4)
  717. +             printf("\tmaxart = %05ld, minart = %05ld\n",
  718. +                 maxart, minart);
  719.           if (fprintf(nhfd,"%s %05ld %05ld %c\n", afline, maxart,
  720.               minart, cansub) == EOF)
  721.               xerror("Active file write failed");
  722. + #endif /* !USG */
  723.       } while (!feof(ohfd));
  724.       if (fclose(nhfd))
  725.           xerror("Active file write failed, %s", errmsg(errno));
  726. !     (void) fclose(ohfd); /* this might unlock inews as a side effect */
  727.   
  728.       (void) rename(ACTIVE, OACTIVE);
  729.       (void) rename(NACTIVE, ACTIVE);
  730.   }
  731.   
  732.   /* Unlink (using unwound tail recursion) all the articles in 'artlist'. */
  733. ***************
  734. *** 928,934 ****
  735.       return 0;
  736.   }
  737.   
  738. ! /* 
  739.    * Count instances of c in s
  740.    */
  741.   chrcnt(s, c)
  742. --- 997,1003 ----
  743.       return 0;
  744.   }
  745.   
  746. ! /*
  747.    * Count instances of c in s
  748.    */
  749.   chrcnt(s, c)
  750. ***************
  751. *** 969,975 ****
  752.       return rc;
  753.   }
  754.   
  755.   /*    Make sure this file is a legal article. */
  756.   islegal(fullname, path, name)
  757.   register char *fullname;
  758. --- 1038,1043 ----
  759. ***************
  760. *** 1065,1075 ****
  761.       if (store(lhs, rhs) < 0)
  762.           xerror("dbm store failed");
  763.   }
  764. ! #endif /* DBM */
  765.   
  766.   xxit(i)
  767.   {
  768. !     sprintf(bfr,"%s.lock", ACTIVE);
  769. !     (void) UNLINK(bfr);
  770.       exit(i);
  771.   }
  772. --- 1133,1201 ----
  773.       if (store(lhs, rhs) < 0)
  774.           xerror("dbm store failed");
  775.   }
  776. ! #else
  777. ! /*
  778. !  * Open the next history subdirectory file
  779. !  */
  780.   
  781. + FILE *nexthistfile(ofp)
  782. + FILE *ofp;
  783. + {
  784. +     static int histfilecounter = -1;
  785. +     if (ofp)
  786. +         fclose(ofp);
  787. +     do {
  788. +         if (++histfilecounter > 9)
  789. +             return NULL;
  790. +         sprintf(bfr, "%s.d/%d", ARTFILE, histfilecounter);
  791. +         if (verbose > 3)
  792. +             printf("reading history file %s\n", bfr);
  793. +         ofp = xfopen(bfr, "r");
  794. +     } while (ofp == NULL);
  795. +     return ofp;
  796. + }
  797. + /*
  798. +  * Rebuild the history subdirectory from LIBDIR/history
  799. +  */
  800. + rebuildhistorydir()
  801. + {
  802. +     char fn[BUFLEN], ofn[BUFLEN];
  803. +     register int i;
  804. +     FILE *subfd[10], *ohfd;
  805. +     /* rebuild history subfiles */
  806. +     (void) sprintf(fn, "%s.od", ARTFILE);
  807. +     if (access(fn,0) != 0)
  808. +         (void) mkdir(fn, 0755);
  809. +     (void) sprintf(fn, "%s.d", ARTFILE);
  810. +     if (verbose)
  811. +         printf("Rebuilding history subfile directory %d.\n", fn);
  812. +     if (access(fn,0) != 0)
  813. +         (void) mkdir(fn, 0755);
  814. +     for (i = 0; i < 10; i++) {
  815. +         (void) sprintf(fn, "%s.d/%c", ARTFILE, i + '0');
  816. +         (void) sprintf(ofn, "%s.od/%c", ARTFILE, i + '0');
  817. +         (void) rename(fn, ofn);
  818. +         close(creat(fn, 0644));
  819. +         subfd[i] = xfopen(fn, "w+");
  820. +     }
  821. +     ohfd = xfopen(ARTFILE, "r");
  822. +     while (fgets(fn, BUFLEN, ohfd) != NULL) {
  823. +         i = findhfdigit(fn) - '0';
  824. +         fputs(fn, subfd[i]);
  825. +     }
  826. +     (void) fclose(ohfd);
  827. +     for (i = 0; i < 10; i++)
  828. +         if (ferror(subfd[i]) || fclose(subfd[i]))
  829. +             xerror("History subfile write");
  830. +     (void) UNLINK(ARTFILE);
  831. + }
  832. + #endif /* !DBM */
  833.   xxit(i)
  834.   {
  835. !     rmlock();
  836.       exit(i);
  837.   }
  838.  
  839. Index: funcs2.c
  840. Prereq: 1.18
  841. *** .d/funcs2.c    Mon Dec 29 18:34:15 1986
  842. --- funcs2.c    Mon Feb 23 22:28:47 1987
  843. ***************
  844. *** 17,23 ****
  845.    */
  846.   
  847.   #ifdef SCCSID
  848. ! static char    *SccsId = "@(#)funcs2.c    1.18    12/29/86";
  849.   #endif /* SCCSID */
  850.   
  851.   #include "params.h"
  852. --- 17,23 ----
  853.    */
  854.   
  855.   #ifdef SCCSID
  856. ! static char    *SccsId = "@(#)funcs2.c    1.19    2/22/87";
  857.   #endif /* SCCSID */
  858.   
  859.   #include "params.h"
  860. ***************
  861. *** 596,616 ****
  862.   histfile(hline)
  863.   char *hline;
  864.   {
  865. -     char *p;
  866.       char chr;    /* least significant digit of article number */
  867.       static char subfile[BUFLEN];
  868.   
  869. !     p = strchr(hline, '@');
  870. !     if (p != NULL && p > hline)
  871.           chr = *(p - 1);
  872.       else
  873.           chr = '0';
  874.       if (!isdigit(chr))
  875.           chr = '0';
  876. !     sprintf(subfile, "%s.d/%c", ARTFILE, chr);
  877. !     if (access(subfile, 04) < 0)
  878. !         return(ARTFILE);
  879. !     return(subfile);
  880.   }
  881.   #endif /* !DBM */
  882.   
  883. --- 596,625 ----
  884.   histfile(hline)
  885.   char *hline;
  886.   {
  887.       char chr;    /* least significant digit of article number */
  888.       static char subfile[BUFLEN];
  889.   
  890. !     chr = findhfdigit(hline);
  891. !     sprintf(subfile, "%s.d/%c", ARTFILE, chr);
  892. !     if (access(subfile, 04) < 0)
  893. !         return(ARTFILE);
  894. !     return(subfile);
  895. ! }
  896. ! findhfdigit(fn)
  897. ! char *fn;
  898. ! {
  899. !     register char *p;
  900. !     register int chr;
  901. !     p = index(fn, '@');
  902. !     if (p != NULL && p > fn)
  903.           chr = *(p - 1);
  904.       else
  905.           chr = '0';
  906.       if (!isdigit(chr))
  907.           chr = '0';
  908. !     return chr;
  909.   }
  910.   #endif /* !DBM */
  911.   
  912. Index: header.h
  913. Prereq: 2.19
  914. *** .d/header.h    Thu Oct 30 16:12:05 1986
  915. --- header.h    Mon Feb 23 22:28:50 1987
  916. ***************
  917. *** 2,8 ****
  918.    * header.h - Article header format
  919.    */
  920.   
  921. ! /*    @(#)header.h    2.19    1/17/86    */
  922.   
  923.   #define NUNREC 50
  924.   
  925. --- 2,8 ----
  926.    * header.h - Article header format
  927.    */
  928.   
  929. ! /*    @(#)header.h    2.20    2/22/87    */
  930.   
  931.   #define NUNREC 50
  932.   
  933. ***************
  934. *** 10,16 ****
  935.   struct    hbuf {
  936.       char    from[BUFLEN];        /* From:        */
  937.       char    path[PATHLEN];        /* Path:        */
  938. !     char    nbuf[BUFLEN];        /* Newsgroups:        */
  939.       char    title[BUFLEN];        /* Subject:        */
  940.       char    ident[BUFLEN];        /* Message-ID:        */
  941.       char    replyto[BUFLEN];    /* Reply-To:        */
  942. --- 10,16 ----
  943.   struct    hbuf {
  944.       char    from[BUFLEN];        /* From:        */
  945.       char    path[PATHLEN];        /* Path:        */
  946. !     char    nbuf[LBUFLEN];        /* Newsgroups:        */
  947.       char    title[BUFLEN];        /* Subject:        */
  948.       char    ident[BUFLEN];        /* Message-ID:        */
  949.       char    replyto[BUFLEN];    /* Reply-To:        */
  950.  
  951. Index: ifuncs.c
  952. Prereq: 2.59
  953. *** .d/ifuncs.c    Wed Dec 17 18:23:15 1986
  954. --- ifuncs.c    Mon Feb 23 22:28:59 1987
  955. ***************
  956. *** 16,22 ****
  957.    */
  958.   
  959.   #ifdef SCCSID
  960. ! static char    *SccsId = "@(#)ifuncs.c    2.59    12/16/86";
  961.   #endif /* SCCSID */
  962.   
  963.   #include "iparams.h"
  964. --- 16,22 ----
  965.    */
  966.   
  967.   #ifdef SCCSID
  968. ! static char    *SccsId = "@(#)ifuncs.c    2.60    2/22/87";
  969.   #endif /* SCCSID */
  970.   
  971.   #include "iparams.h"
  972. ***************
  973. *** 603,618 ****
  974.   char *hline;
  975.   {
  976.       register FILE *hfp;
  977. -     datum lhs, rhs;
  978. -     long fpos;
  979.       register char *p;
  980.   
  981.       hfp = xfopen(ARTFILE, "a");
  982.       (void) fseek(hfp, 0L, 2); /* Unisoft 5.1 doesn't seek to EOF on 'a' */
  983.       fpos = ftell(hfp);
  984.       fprintf(hfp, "%s\n", hline);
  985.       (void) fclose(hfp);
  986.   #ifdef DBM
  987.       /* We assume that history has already been called, calling dbminit. */
  988.       p = index(hline, '\t');
  989.       if (p)
  990. --- 603,635 ----
  991.   char *hline;
  992.   {
  993.       register FILE *hfp;
  994.       register char *p;
  995. + #ifdef DBM
  996. +     long fpos;
  997. + #endif /* !DBM */
  998.   
  999. + #ifndef DBM
  1000. +     if (strcmp((p = histfile(hline)), ARTFILE) != 0) {
  1001. +     /* If the history subfile is accessible */
  1002. +         if ((hfp = xfopen(p, "a")) != NULL ) { /* If we can append */
  1003. +             fprintf(hfp, "%s\n", hline);   /* Append */
  1004. +             (void) fclose(hfp);
  1005. +         } else
  1006. +             logerr("Unable to append to %s: %s", p, errmsg(errno));
  1007. +     } else
  1008. + #endif /* !DBM */
  1009. +     {
  1010.       hfp = xfopen(ARTFILE, "a");
  1011.       (void) fseek(hfp, 0L, 2); /* Unisoft 5.1 doesn't seek to EOF on 'a' */
  1012. + #ifdef DBM
  1013.       fpos = ftell(hfp);
  1014. + #endif /* !DBM */
  1015.       fprintf(hfp, "%s\n", hline);
  1016.       (void) fclose(hfp);
  1017. +     }
  1018.   #ifdef DBM
  1019. +     {
  1020. +     datum lhs, rhs;
  1021.       /* We assume that history has already been called, calling dbminit. */
  1022.       p = index(hline, '\t');
  1023.       if (p)
  1024. ***************
  1025. *** 623,638 ****
  1026.       rhs.dptr = (char *)&fpos;
  1027.       rhs.dsize = sizeof fpos;
  1028.       store(lhs, rhs);
  1029. ! #else /* !DBM */
  1030. !     if (strcmp(p = histfile(hline), ARTFILE) != 0)
  1031. !     /* If the history subfile is accessible */
  1032. !         if ((hfp = xfopen(p, "a")) != NULL ) { /* If we can append */
  1033. !             fprintf(hfp, "%s\n", hline);   /* Append */
  1034. !             (void) fclose(hfp);
  1035. !         } else
  1036. !             logerr("Unable to append to %s: %s", p, errmsg(errno));
  1037. ! #endif /* !DBM */
  1038.       idunlock();
  1039.   }
  1040.   
  1041. --- 640,647 ----
  1042.       rhs.dptr = (char *)&fpos;
  1043.       rhs.dsize = sizeof fpos;
  1044.       store(lhs, rhs);
  1045. !     }
  1046. ! #endif /* DBM */
  1047.       idunlock();
  1048.   }
  1049.   
  1050. Index: inews.c
  1051. Prereq: 2.73
  1052. *** .d/inews.c    Mon Dec 29 18:34:08 1986
  1053. --- inews.c    Mon Feb 23 22:29:09 1987
  1054. ***************
  1055. *** 17,27 ****
  1056.    */
  1057.   
  1058.   #ifdef SCCSID
  1059. ! static char    *SccsId = "@(#)inews.c    2.73    12/29/86";
  1060.   #endif /* SCCSID */
  1061.   
  1062.   #include "iparams.h"
  1063. - #include <errno.h>
  1064.   
  1065.   #ifdef BSD4_2
  1066.   # include <sys/dir.h>
  1067. --- 17,26 ----
  1068.    */
  1069.   
  1070.   #ifdef SCCSID
  1071. ! static char    *SccsId = "@(#)inews.c    2.74    2/22/87";
  1072.   #endif /* SCCSID */
  1073.   
  1074.   #include "iparams.h"
  1075.   
  1076.   #ifdef BSD4_2
  1077.   # include <sys/dir.h>
  1078. ***************
  1079. *** 114,120 ****
  1080.       struct group    *gp;    /* struct for group lookup        */
  1081.       register int    i;
  1082.       FILE    *mfd;        /* mail file file-descriptor        */
  1083. -     char    cbuf[BUFLEN];    /* command buffer            */
  1084.   
  1085.       /* uuxqt doesn't close all it's files */
  1086.       for (i = 3; !close(i); i++)
  1087. --- 113,118 ----
  1088. ***************
  1089. *** 156,162 ****
  1090.   #ifdef    LOCKF
  1091.       lockf(fileno(actfp), F_ULOCK, 0);
  1092.   #else    /* !LOCKF */
  1093. !     UNLINK(ACTIVE, bfr);
  1094.   #endif /* V7 */
  1095.   #endif    /* !BSD4_2 */
  1096.       if (argc > 1 && !strcmp(*(argv+1), "-U")) {
  1097. --- 154,160 ----
  1098.   #ifdef    LOCKF
  1099.       lockf(fileno(actfp), F_ULOCK, 0);
  1100.   #else    /* !LOCKF */
  1101. !     UNLINK(bfr);
  1102.   #endif /* V7 */
  1103.   #endif    /* !BSD4_2 */
  1104.       if (argc > 1 && !strcmp(*(argv+1), "-U")) {
  1105. ***************
  1106. *** 184,223 ****
  1107.       header.title[0] = header.nbuf[0] = filename[0] = '\0';
  1108.   
  1109.       /* check for existence of special files */
  1110. !     if (!rwaccess(ARTFILE)) {
  1111. !         mfd = mailhdr((struct hbuf *)NULL, exists(ARTFILE) ? "Unwritable files!" : "Missing files!");
  1112. !         if (mfd != NULL) {
  1113. ! #ifdef HIDDENNET
  1114. !             fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
  1115. ! #else /* !HIDDENNET */
  1116. !             fprintf(mfd,"System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ARTFILE);
  1117. ! #endif /* !HIDDENNET */
  1118. !             (void) sprintf(cbuf, "touch %s;chmod 666 %s", ARTFILE, ARTFILE);
  1119. !             (void) system(cbuf);
  1120. !             if (rwaccess(ARTFILE))
  1121. !                 fprintf(mfd, "The problem has been taken care of.\n");
  1122. !             else
  1123. !                 fprintf(mfd, "Corrective action failed - check suid bits.\n");
  1124. !             (void) mclose(mfd);
  1125. !         }
  1126. !     }
  1127. !     if (!rwaccess(ACTIVE)) {
  1128. !         mfd = mailhdr((struct hbuf *)NULL, exists(ACTIVE) ? "Unwritable files!" : "Missing files!");
  1129. !         if (mfd != NULL) {
  1130. ! #ifdef HIDDENNET
  1131. !             fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
  1132. ! #else /* !HIDDENNET */
  1133. !             fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ACTIVE);
  1134. ! #endif /* !HIDDENNET */
  1135. !             (void) sprintf(cbuf, "touch %s;chmod 666 %s", ACTIVE, ACTIVE);
  1136. !             (void) system(cbuf);
  1137. !             if (rwaccess(ACTIVE))
  1138. !                 fprintf(mfd, "The problem has been taken care of.\n");
  1139. !             else
  1140. !                 fprintf(mfd, "Corrective action failed - check suid bits.\n");
  1141. !             (void) mclose(mfd);
  1142. !         }
  1143. !     }
  1144.       SigTrap = FALSE;    /* true if a signal has been caught */
  1145.       if (mode != PROC) {
  1146.           (void) signal(SIGHUP, onsig);
  1147. --- 182,193 ----
  1148.       header.title[0] = header.nbuf[0] = filename[0] = '\0';
  1149.   
  1150.       /* check for existence of special files */
  1151. ! #ifdef DBM
  1152. !     chkfile(ARTFILE);
  1153. ! #else
  1154. !     chkdir(ARTFILE);
  1155. ! #endif DBM
  1156. !     chkfile(ACTIVE);
  1157.       SigTrap = FALSE;    /* true if a signal has been caught */
  1158.       if (mode != PROC) {
  1159.           (void) signal(SIGHUP, onsig);
  1160. ***************
  1161. *** 487,493 ****
  1162. --- 457,562 ----
  1163.   
  1164.       /* Do the actual insertion. */
  1165.       insert();
  1166. +     /* NOTREACHED */
  1167.   }
  1168. + /* check for existence of file */
  1169. + static chkfile(f)
  1170. + char *f;
  1171. + {
  1172. +     FILE    *mfd;        /* mail file file-descriptor        */
  1173. +     char    cbuf[BUFLEN];    /* command buffer            */
  1174. +     if (!rwaccess(f)) {
  1175. +         mfd = mailhdr((struct hbuf *)NULL, exists(f) ? "Unwritable files!" : "Missing files!");
  1176. +         if (mfd != NULL) {
  1177. + #ifdef HIDDENNET
  1178. +             fprintf(mfd, "System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, f);
  1179. + #else /* !HIDDENNET */
  1180. +             fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, f);
  1181. + #endif /* !HIDDENNET */
  1182. +             (void) sprintf(cbuf, "touch %s;chmod 666 %s", f, f);
  1183. +             (void) system(cbuf);
  1184. +             if (rwaccess(f))
  1185. +                 fprintf(mfd, "The problem has been taken care of.\n");
  1186. +             else
  1187. +                 fprintf(mfd, "Corrective action failed - check suid bits.\n");
  1188. +             (void) mclose(mfd);
  1189. +         }
  1190. +     }
  1191. + }
  1192. + #ifndef DBM
  1193. + /* check for existence of directory */
  1194. + static chkdir(d)
  1195. + char *d;
  1196. + {
  1197. +     FILE    *mfd;        /* mail file file-descriptor        */
  1198. +     char    dir[BUFLEN];    /* holds directory name            */
  1199. +     sprintf(dir, "%s.d", d);
  1200. +     if (eaccess(dir, 07) != 0) {
  1201. +         mfd = mailhdr((struct hbuf *)NULL, exists(dir) ? "Unwritable diretories!" : "Missing directories!");
  1202. +         if (mfd != NULL) {
  1203. + #ifdef HIDDENNET
  1204. +             fprintf(mfd, "System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, dir);
  1205. + #else /* !HIDDENNET */
  1206. +             fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, dir);
  1207. + #endif /* !HIDDENNET */
  1208. +             (void) mkdir(dir, 0775);
  1209. +             if (eaccess(dir, 07) == 0)
  1210. +                 fprintf(mfd, "The problem has been taken care of.\n");
  1211. +             else
  1212. +                 fprintf(mfd, "Corrective action failed - check suid bits.\n");
  1213. +             (void) mclose(mfd);
  1214. +         }
  1215. +     }
  1216. + }
  1217. + /*
  1218. +  * This version of access checks against effective uid and effective gid
  1219. +  */
  1220. + eaccess(name, mode)
  1221. + register char *name;
  1222. + register int mode;
  1223. + {    
  1224. +     struct stat statb;
  1225. +     int euserid = geteuid();
  1226. +     int egroupid = getegid();
  1227. +     if (stat(name, &statb) == 0) {
  1228. +         if (euserid == 0) {
  1229. +             if ((statb.st_mode&S_IFMT) != S_IFREG || mode != 1)
  1230. +                 return 0;
  1231. +                 /* root needs execute permission for someone */
  1232. +             mode = (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
  1233. +         }
  1234. +         else if (euserid == statb.st_uid)
  1235. +             mode <<= 6;
  1236. +         else if (egroupid == statb.st_gid)
  1237. +             mode <<= 3;
  1238. + #ifdef BSD4_2
  1239. +         /* in BSD4_2 you can be in several groups */
  1240. +         else {
  1241. +             int groups[NGROUPS];
  1242. +             register int n;
  1243. +             n = getgroups(NGROUPS,groups);
  1244. +             while(--n >= 0) {
  1245. +                 if(groups[n] == statb.st_gid) {
  1246. +                     mode <<= 3;
  1247. +                     break;
  1248. +                 }
  1249. +             }
  1250. +         }
  1251. + #endif /* BSD4_2 */
  1252. +         if (statb.st_mode & mode)
  1253. +             return 0;
  1254. +     }
  1255. +     return -1;
  1256. + }
  1257. + #endif /* DBM */
  1258.   
  1259.   dospool(batchcmd, dolhwrite)
  1260.   char *batchcmd;
  1261.  
  1262. Index: patchlevel.h
  1263. Prereq: 3
  1264. *** .d/patchlevel.h    Mon Dec 29 18:34:15 1986
  1265. --- patchlevel.h    Mon Feb 23 22:29:11 1987
  1266. ***************
  1267. *** 1,3 ****
  1268. ! #define    PATCHLEVEL    3
  1269.   
  1270. ! #define NEWS_VERSION   "B 2.11 12/29/86"
  1271. --- 1,3 ----
  1272. ! #define    PATCHLEVEL    4
  1273.   
  1274. ! #define NEWS_VERSION   "B 2.11 2/22/87"
  1275. Index: rfuncs.c
  1276. Prereq: 2.39
  1277. *** .d/rfuncs.c    Mon Dec 29 18:34:11 1986
  1278. --- rfuncs.c    Mon Feb 23 22:29:19 1987
  1279. ***************
  1280. *** 16,22 ****
  1281.    */
  1282.   
  1283.   #ifdef SCCSID
  1284. ! static char    *SccsId = "@(#)rfuncs.c    2.39    12/23/86";
  1285.   #endif /* SCCSID */
  1286.   
  1287.   /*LINTLIBRARY*/
  1288. --- 16,22 ----
  1289.    */
  1290.   
  1291.   #ifdef SCCSID
  1292. ! static char    *SccsId = "@(#)rfuncs.c    2.40    2/22/87";
  1293.   #endif /* SCCSID */
  1294.   
  1295.   /*LINTLIBRARY*/
  1296. ***************
  1297. *** 728,734 ****
  1298.   lg_cmp(p1, p2)
  1299.   int *p1, *p2;
  1300.   {
  1301. !     return *p1 > *p2;
  1302.   }
  1303.   
  1304.   list_group(lgroup, displines, flag, pngsize)
  1305. --- 728,734 ----
  1306.   lg_cmp(p1, p2)
  1307.   int *p1, *p2;
  1308.   {
  1309. !     return *p1 - *p2;
  1310.   }
  1311.   
  1312.   list_group(lgroup, displines, flag, pngsize)
  1313. ***************
  1314. *** 831,836 ****
  1315. --- 831,837 ----
  1316.               break;
  1317.       }
  1318.       (void) free(lg_array);
  1319. +     lg_array = NULL;
  1320.   
  1321.   }
  1322.   
  1323. /* End of text from mirror:news.software.b */
  1324.